package SimulatorComponents;

import java.io.FileNotFoundException;
import java.util.Scanner;

import DataFormatConversionComponents.NumberConverter;
import Exceptions.InvalidMemoryAllocationException;
/**
 * 
 * This class simulates the AR2RISC microprocessor, initializing the AR2RISC type
 * object along with the mode of execution control integer
 *
 */
public class Simulator {

	private AR2RISC myMP;
	private int mode;
	
	public Simulator(int mode){

		System.out.println( "SIMULATOR" );

		this.mode = mode;
		myMP = new AR2RISC(mode);
		
	}
	
	/**
	 * Method uses object of type MemoryLoader to read the input file and load it into memory 
	 *
	 * @return integer count of how many instructions were written in loaded into memory
	 * @throws FileNotFoundException 
	 * @throws InvalidMemoryAllocationException
	 */
	public int loadProgram() throws FileNotFoundException, InvalidMemoryAllocationException {
		
		MemoryLoader memLoader = new MemoryLoader();
		return memLoader.load( myMP.getMem() );
	}
	
	/**
	 * This starts the simulation
	 */
	public void simulate(int instructionCount) throws FileNotFoundException, InvalidMemoryAllocationException{

		//initialize the program counter to zero
		int new_pc[]={0,0,0,0,0,0,0,0};
		myMP.getPc().set(new_pc);
		//let AR2RISC's Control Unit know how many 16-bit instructions have been stored in memory
		myMP.getControlUnit().setInstructionCount(instructionCount);
		
		myMP.start();
		
		if( mode == 1 )	
			displaySystem();

	}
	
	/**
	 * This method displays all the AR2RISC's components: program counter, instruction register,
	 * status register, accumulator register, general purpose registers, keyboard, display, and main memory
	 */
	public void displaySystem(){
		int temp[];
		NumberConverter converter = new NumberConverter();

		System.out.println("\nPROGRAM COUNTER:");
		temp = myMP.getPc().get();
		for(int i = 0; i < temp.length; i++ )
			System.out.print( temp[i] );

		System.out.println("\n\nINSTRUCTION REGISTER:");
		temp = myMP.getIr().get();
		for(int i = 0; i < temp.length; i++ )
			System.out.print( temp[i] );

		System.out.println("\n\nSTATUS REGISTER:");
		temp = myMP.getSr().get();
		for(int i = 0; i < temp.length; i++ )
			System.out.print( temp[i] );

		System.out.println("\n\nACCUMULATOR REGISTER:");
		temp = myMP.getAcc().get();
		for(int i = 0; i < temp.length; i++ )
			System.out.print( temp[i] );

		System.out.println("\n\nGENERAL PURPOSE REGISTERS:");
		for( int i = 0; i < 8; i++ ){
			temp = myMP.getRegs().read(i);
			System.out.print("R" + i +" : " );
			for( int j = 0; j < temp.length; j++ ){
				System.out.print( temp[j] );
			}
			System.out.println("\n");
		}

		System.out.println("\nKEYBOARD:");
		temp = myMP.getMem().readByte(250);
		System.out.print( converter.ASCIIToChar( converter.binaryToDecimal( temp ) ) + " ");
		temp = myMP.getMem().readByte(251);
		System.out.print( converter.ASCIIToChar( converter.binaryToDecimal( temp ) ) + " ");
		

		System.out.println("\n\nDISPLAY:");		
		for(int i = 252; i < 256; i++ ){
			temp = myMP.getMem().readByte(i);
			System.out.print( converter.ASCIIToChar( converter.binaryToDecimal( temp ) ) + " ");
		}

		System.out.println("\nMAIN MEMORY: \n(address : content)");

		for( int i = 0; i < 255; i += 2 ){
			temp = myMP.getMem().readByte(i);
			System.out.print(i + "-" + (i + 1) + " : " );
			System.out.print( converter.binaryToHex(temp) + " - ");
			temp = myMP.getMem().readByte( i + 1 );
			System.out.print( converter.binaryToHex(temp) );
			System.out.println("\n");
		}

		
	}
	
}
